package mybatisgen.plugin;

import com.itfsw.mybatis.generator.plugins.utils.CommTools;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.codegen.mybatis3.ListUtilities;
import org.mybatis.generator.codegen.mybatis3.MyBatis3FormattingUtilities;

import java.util.ArrayList;
import java.util.List;

@Slf4j
public class BatchInsertPlugin extends PluginAdapter {
	private static final String METHOD_BATCH_INSERT = "batchInsert";  // 方法名
	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean validate(List<String> warnings) {
		return true;
	}


	@Override
	public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
		// 1. batchInsert
		Method mBatchInsert = new Method(METHOD_BATCH_INSERT);
		mBatchInsert.setReturnType(FullyQualifiedJavaType.getIntInstance());
		mBatchInsert.setAbstract(true);
		// 添加参数
		FullyQualifiedJavaType tList = FullyQualifiedJavaType.getNewListInstance();
		tList.addTypeArgument(introspectedTable.getRules().calculateAllFieldsClass());
		mBatchInsert.addParameter(new Parameter(tList, "list", "@Param(\"list\")"));
		// interface 增加方法
		interfaze.addMethod(mBatchInsert);
		log. debug("itfsw(批量插入插件):" + interfaze.getType().getShortName() + "增加batchInsert方法。");
		return true;
	}

	@Override
	public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
		// 1. batchInsert
		XmlElement batchInsertEle = new XmlElement("insert");
		batchInsertEle.addAttribute(new Attribute("id", METHOD_BATCH_INSERT));
		// 参数类型
		batchInsertEle.addAttribute(new Attribute("parameterType", "map"));

		// 使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置的领域模型属性中。所以只支持MYSQL和SQLServer
		CommTools.useGeneratedKeys(batchInsertEle, introspectedTable);

		StringBuilder insertClause = new StringBuilder();
		StringBuilder valuesClause = new StringBuilder();

		insertClause.append("insert into "); //$NON-NLS-1$
		insertClause.append(introspectedTable.getFullyQualifiedTableNameAtRuntime());
		insertClause.append(" ("); //$NON-NLS-1$

		valuesClause.append(" ("); //$NON-NLS-1$

		List<String> valuesClauses = new ArrayList<String>();
		List<IntrospectedColumn> columns = ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns());
		for (int i = 0; i < columns.size(); i++) {
			IntrospectedColumn introspectedColumn = columns.get(i);

			insertClause.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn));

			// 生成foreach下插入values
			valuesClause.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn, "item."));
			if (i + 1 < columns.size()) {
				insertClause.append(", "); //$NON-NLS-1$
				valuesClause.append(", "); //$NON-NLS-1$
			}
		}

		insertClause.append(')');
		batchInsertEle.addElement(new TextElement(insertClause.toString()));

		valuesClause.append(')');
		valuesClauses.add(valuesClause.toString());


		// 添加foreach节点
		XmlElement foreachElement = new XmlElement("foreach");
		foreachElement.addAttribute(new Attribute("collection", "list"));
		foreachElement.addAttribute(new Attribute("item", "item"));
		foreachElement.addAttribute(new Attribute("separator", ","));

		for (String clause : valuesClauses) {
			foreachElement.addElement(new TextElement(clause));
		}

		// values 构建
		batchInsertEle.addElement(new TextElement("values"));
		batchInsertEle.addElement(foreachElement);
		if (context.getPlugins().sqlMapInsertElementGenerated(batchInsertEle, introspectedTable)) {
			document.getRootElement().addElement(batchInsertEle);
			 log. debug("itfsw(批量插入插件):" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加batchInsert实现方法。");
		}
		return true;
	}
}